Map of TfL zones London
Table of Contents
Some time ago I created a map of the TfL zones in London and would like to document here how I went about it.
First of all, the most important information: The map is located at https://umap.openstreetmap.de/de/map/london-tfl-zones_78601.
Why?
Well, because I wanted to have a graphical representation of information that I couldn’t find on the TfL website. The Tube station closest to my accommodation is in zone 3 and so the ticket costs me more than if it were in zone 1 or 2. Is it worth walking a few hundred metres further to a station that is still in the cheaper zone? Where exactly is the border between the fare zones? And if I then realise that I really need zone 3: what other possible destinations are in the zone? The famous map of the London Tube network is excellent for making the routes easy to recognise, but I couldn’t find any answers to these questions.
I have already found a similar map with Google maps, but there only the zones themselves are available on the map, but not the routes. There are also no markers for the stations within zones 1-3.
Creating the points for the stations
The first step was to get all stations with the information in which zone they are located. Fortunately, the Tube stations in London are well and above all consistently maintained in OSM, there is an attribute ‘fare_zone’.
The first attempt to solve this using Overpass Turbo looked like this:
|
|
Here is the corresponding output1:
So are these the stations that are in zone 1? What are the pitfalls? Let’s zoom in a little:
Even after I extended the area accordingly and then also got the stations within the City of London, zone 1 was still incomplete. The query only shows me the results where the attribute “fare_zone” has the exact value “1”. However, some stations are located on the border to zone 2, where the attribute has the value “1;2”, which was not taken into account in the original query. I only realised this error later.
With this knowledge, I have now created several queries, in each of which I have adjusted the value for the “fare_zone”, downloaded the result of the queries as GeoJSON and uploaded it to umap as a new layer.
Drawing lines
Tube / London Underground
Once I have entered all the stations, the next thing I want to know is which line goes where. For this I have chosen the easiest way (which should of course lead to problems later):
|
|
Simply query all lines one after the other; instead of a node, a way is now searched for. This worked well in the example above. But here, too, two errors have crept in.
For the District Line, the result of the query looks like this:
way["line"~"District"](area.searchArea);
Elizabeth Line and DLR
The previous process worked quite well. At least until I came to the Elizabeth Line, which opened a few years ago. This has a special role and is not part of the regular Tube network, even though the normal tickets are valid within the 9 fare zones. As the line was also listed on the official Tube map, I wanted to have it on my map as well. But the query for
way["line"~"Elizabeth"](area.searchArea);
brought no results. In contrast to the regular lines, this cannot be found as a way, but as a relation. Line 3 now reads:
relation["name"~"Elizabeth line"](area.searchArea);
With the relation, however, I have included all the stations as well as the tracks. I deleted these manually or added them as points in a separate layer where the Elizabeth Line runs outside Zone 9.
When inserting the data for DLR, it turned out that some stations were also missing there. Did I mention above that the OSM data is consistent? Yes, but only for the Tube. Well, the “fare_zone” is only maintained for a few DLR stations. So here too, the relation including the stations was downloaded via Overpass Turbo and uploaded to umap, then the new stations were moved to the corresponding map layer.
London Overground
The recently renamed London Overground lines have also been added, but are hidden by default for clarity. The query for the relation also provides markers for the stop position at most stations, but they are missing in some places. Manual reworking was necessary here.
Fine-tuning
Once all the data had been exported from Overpass Turbo and imported into individual layers on umap.openstreetmap.de, some fine-tuning was still required.
unwanted objects
The queries for the lines sometimes contain objects that are not part of the line. For example, there is a building in the query for the District line that used to be the Osterley & Spring Grove station until it was closed 90 years ago.
However, some buildings are also included in the results on other lines, often the depots.
Colours
It is practical for the routes if the colours are consistent. The TfL made a large part of the design guidelines publicly accessible, but the colour codes are not specified in hex format. It doesn’t matter, a conversion from RGB to hex is possible without any problems. Or you can use the colour codes already stored in the respective routes in OSM. Stations that are only in one zone have been given a colour from the Progress Pride Flag. Stations that are in two zones are shown in grey and everything outside zone 9 in black.
line width
The line width had to be adjusted manually in some places as the lines overlap and would otherwise no longer be visible. The yellow of the Circle Line was painted slightly wider so that it can still be seen under the green line of the District Line, which runs the same for long stretches. The ‘Hammersmith & City Line’ has also been adjusted, here with a dashed line.
Still on the to-do list
Currently, only the Tube, London Overground (hidden by default for clarity, but available), DLR and Elizabeth Line lines are on the map. In the future, regional train connections from other operators may be added.
-
Copyright notice: All screenshots in this blog post contain map material from OpenStreetMap, © OpenStreetMap contributors. ↩︎
-
Vibe coding: Feeding an AI with a prompt, which outputs the appropriate code and usually using this code unchecked without understanding it. (More on this in the article “Vibe coding” on Wikipedia) ↩︎